package com.bestcem.xm.common.core.uitls;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.symmetric.AES;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.*;

@UtilityClass
public class SignUtil {

    // ECB模式和CBC 模式俩者区别就是 ECB 不需要 iv偏移量，而CBC需要。
    private static final String IV_KEY = "0000000000000000";

    public String genSign(Map<String, Object> map, String signKey) {

        List<String> list = new ArrayList<>();
        List<String> keyList = new ArrayList<>(map.keySet());
        Collections.sort(keyList);
        keyList.forEach(key -> {
            list.add(key);
            Object value = map.get(key);
            if (value instanceof Map) {
                list.add(genSign(BeanUtil.beanToMap(value), signKey));
            } else if (value instanceof List<?>) {
                List<String> strList = new ArrayList<>();
                for (Object v : (List<?>) value) {
                    strList.add(genSignStr(v, signKey));
                }
                list.add(String.join(StrUtil.EMPTY, strList));
            } else if (value instanceof Boolean && !(Boolean) value) {
                list.add(StrUtil.EMPTY);
            } else {
                list.add(String.valueOf(value));
            }
        });
        list.add(signKey);
        return DigestUtil.md5Hex(String.join("|", list));
    }


    public String genSignStr(Object data, String signKey) {
        if (data instanceof Map) {
            return genSign(BeanUtil.beanToMap(data), signKey);
        } else if (data instanceof List<?>) {
            List<String> strList = new ArrayList<>();
            for (Object value : (List<?>) data) {
                strList.add(genSignStr(value, signKey));
            }
            return String.join(StrUtil.EMPTY, strList);
        } else if (data instanceof Boolean && !(Boolean) data) {
            return StrUtil.EMPTY;
        } else {
            return String.valueOf(data);
        }
    }


    public boolean checkSign(Map<String, Object> map, String signKey, String signField) {
        if (Validator.isNull(map)) {
            return false;
        }
        Map<String, Object> copyMap = new HashMap<>(map);
        if (StringUtils.isBlank(signField)) {
            signField = "sig";
        }
        String sign = Convert.toStr(copyMap.get(signField));
        if (StringUtils.isBlank(sign)) {
            return false;
        }
        copyMap.remove(signField);
        // 样本投放的idy_sid由su拼接,不参与验签
        copyMap.remove("idy_sid");
        return sign.equals(genSign(copyMap, signKey));
    }


    public boolean checkSign(Map<String, Object> map, String signKey) {
        return checkSign(map, signKey, "sig");
    }

    public String encryptFromString(String aesKey, String data, Mode mode, Padding padding) {
        AES aes = new AES(mode, padding, new SecretKeySpec(aesKey.getBytes(), "AES"));
        return aes.encryptBase64(data, StandardCharsets.UTF_8);
    }

    public String decryptFromString(String aesKey, String data, Mode mode, Padding padding) {
        AES aes = new AES(mode, padding, new SecretKeySpec(aesKey.getBytes(), "AES"));
        byte[] decryptDataBase64 = aes.decrypt(data);
        return new String(decryptDataBase64, StandardCharsets.UTF_8);

    }
}
